home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * CagdCMrg.c - Surface/Surface merging routine. *
- *******************************************************************************
- * Written by Gershon Elber, Sep 92. *
- ******************************************************************************/
-
- #include "cagd_loc.h"
-
- static void InterpolateLinearSeg(CagdRType *V1, CagdRType *V2, int Len,
- int Step);
-
- /******************************************************************************
- * Merge two surfaces in the provided direction Dir. If SameEdge, it is *
- * assumed last edge of Srf1 is identical to first edge of Srf2 and one row *
- * is dropped from new mesh. Otherwise a ruled surface is fit between the two *
- * edges. *
- ******************************************************************************/
- CagdSrfStruct *CagdMergeSrfSrf(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2,
- CagdSrfDirType Dir, CagdBType SameEdge)
- {
- CagdBType IsNotRational;
- int i, j, UOrder, VOrder, ULen1, VLen1, ULen2, VLen2, MaxCoord, Length;
- CagdRType **Points1, **Points2, **Points;
- CagdPointType SrfPType;
- CagdSrfStruct *Srf;
-
- /* Make surfaces compatible: */
- Srf1 = CagdSrfCopy(Srf1);
- Srf2 = CagdSrfCopy(Srf2);
-
- switch (Dir) {
- case CAGD_CONST_U_DIR:
- case CAGD_CONST_V_DIR:
- if (!CagdMakeSrfsCompatible(&Srf1, &Srf2, TRUE, TRUE,
- Dir == CAGD_CONST_V_DIR,
- Dir == CAGD_CONST_U_DIR))
- FATAL_ERROR(CAGD_ERR_SRF_FAIL_CMPT);
- break;
- default:
- FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
- break;
- }
-
- /* Verify surface geometric types. */
- switch (Srf1 -> GType) {
- case CAGD_SBEZIER_TYPE:
- Srf = CnvrtBezier2BsplineSrf(Srf1);
- CagdSrfFree(Srf1);
- Srf1 = Srf;
- Srf = CnvrtBezier2BsplineSrf(Srf2);
- CagdSrfFree(Srf2);
- Srf2 = Srf;
- break;
- case CAGD_SBSPLINE_TYPE:
- break;
- case CAGD_SPOWER_TYPE:
- FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
- break;
- default:
- FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
- break;
- }
-
- UOrder = Srf1 -> UOrder;
- VOrder = Srf1 -> VOrder;
- ULen1 = Srf1 -> ULength;
- VLen1 = Srf1 -> VLength;
- ULen2 = Srf2 -> ULength;
- VLen2 = Srf2 -> VLength;
- Points1 = Srf1 -> Points;
- Points2 = Srf2 -> Points;
- IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf1);
- MaxCoord = CAGD_NUM_OF_PT_COORD(Srf1 -> PType),
- SrfPType = CAGD_MAKE_PT_TYPE(!IsNotRational, MaxCoord);
-
- switch (Dir) {
- case CAGD_CONST_U_DIR:
- Length = SameEdge ? ULen1 + ULen2 - 1 : ULen1 + ULen2 + UOrder - 2;
- Srf = BspSrfNew(Length, VLen1, UOrder, VOrder, SrfPType);
-
- /* Update knot vectors. We assume open end condition here... */
- CAGD_GEN_COPY(Srf -> UKnotVector, Srf1 -> UKnotVector,
- (ULen1 + UOrder - 1) * sizeof(CagdRType));
- CAGD_GEN_COPY(Srf -> VKnotVector, Srf1 -> VKnotVector,
- (VLen1 + VOrder) * sizeof(CagdRType));
-
- if (SameEdge) {
- /* Copy kv of second surface immediately after. */
- CAGD_GEN_COPY(&Srf -> UKnotVector[ULen1 + UOrder - 1],
- &Srf2 -> UKnotVector[UOrder],
- ULen2 * sizeof(CagdRType));
- BspKnotAffineTrans(&Srf -> UKnotVector[ULen1 + UOrder - 1],
- ULen2,
- Srf -> UKnotVector[ULen1 + UOrder - 2] -
- Srf2 -> UKnotVector[0],
- 1.0);
- }
- else {
- /* Copy kv of second surface order after. */
- CAGD_GEN_COPY(&Srf -> UKnotVector[ULen1 + UOrder - 1],
- &Srf2 -> UKnotVector[1],
- (ULen2 + UOrder - 1) * sizeof(CagdRType));
- BspKnotAffineTrans(&Srf -> UKnotVector[ULen1 + UOrder - 1],
- ULen2 + UOrder - 1,
- Srf -> UKnotVector[ULen1 + UOrder - 2] -
- Srf -> UKnotVector[ULen1 + UOrder - 1] + 1.0,
- 1.0);
- }
-
- Points = Srf -> Points;
-
- for (i = 0; i < VLen1; i++) {
- for (j = IsNotRational; j <= MaxCoord; j++) {
- CAGD_GEN_COPY(&Points[j][CAGD_MESH_UV(Srf, 0, i)],
- &Points1[j][CAGD_MESH_UV(Srf1, 0, i)],
- ULen1 * sizeof(CagdRType));
- if (SameEdge) {
- /* Copy row of second surface immediately after. */
- CAGD_GEN_COPY(
- &Points[j][CAGD_MESH_UV(Srf, ULen1 - 1, i)],
- &Points2[j][CAGD_MESH_UV(Srf2, 0, i)],
- ULen2 * sizeof(CagdRType));
- }
- else {
- /* Copy row of 2nd srf order after and lin. interp. */
- CAGD_GEN_COPY(
- &Points[j][CAGD_MESH_UV(Srf, ULen1 + UOrder - 2, i)],
- &Points2[j][CAGD_MESH_UV(Srf2, 0, i)],
- ULen2 * sizeof(CagdRType));
- InterpolateLinearSeg(
- &Points[j][CAGD_MESH_UV(Srf, ULen1 - 1, i)],
- &Points[j][CAGD_MESH_UV(Srf, ULen1 + UOrder - 2, i)],
- UOrder, 1);
- }
- }
- }
- break;
- case CAGD_CONST_V_DIR:
- Length = SameEdge ? VLen1 + VLen2 - 1 : VLen1 + VLen2 + VOrder - 2;
- Srf = BspSrfNew(ULen1, Length, UOrder, VOrder, SrfPType);
-
- /* Update knot vectors. We assume open end condition here... */
- CAGD_GEN_COPY(Srf -> UKnotVector, Srf1 -> UKnotVector,
- (ULen1 + UOrder) * sizeof(CagdRType));
- CAGD_GEN_COPY(Srf -> VKnotVector, Srf1 -> VKnotVector,
- (VLen1 + VOrder - 1) * sizeof(CagdRType));
-
- if (SameEdge) {
- /* Copy kv of second surface immediately after. */
- CAGD_GEN_COPY(&Srf -> VKnotVector[VLen1 + VOrder - 1],
- &Srf2 -> VKnotVector[VOrder],
- VLen2 * sizeof(CagdRType));
- BspKnotAffineTrans(&Srf -> VKnotVector[VLen1 + VOrder - 1],
- VLen2,
- Srf -> VKnotVector[VLen1 + VOrder - 2] -
- Srf2 -> VKnotVector[0],
- 1.0);
- }
- else {
- /* Copy kv of second surface order after. */
- CAGD_GEN_COPY(&Srf -> VKnotVector[VLen1 + VOrder - 1],
- &Srf2 -> VKnotVector[1],
- (VLen2 + VOrder - 1) * sizeof(CagdRType));
- BspKnotAffineTrans(&Srf -> VKnotVector[VLen1 + VOrder - 1],
- VLen2 + VOrder - 1,
- Srf -> VKnotVector[VLen1 + VOrder - 2] -
- Srf -> VKnotVector[VLen1 + VOrder - 1] + 1.0,
- 1.0);
- }
-
- Points = Srf -> Points;
-
- for (i = 0; i < ULen1; i++) {
- for (j = IsNotRational; j <= MaxCoord; j++) {
- CAGD_GEN_COPY_STEP(&Points[j][CAGD_MESH_UV(Srf, i, 0)],
- &Points1[j][CAGD_MESH_UV(Srf1, i, 0)],
- VLen1, ULen1, ULen1, CagdRType);
- if (SameEdge) {
- /* Copy col of second surface immediately after. */
- CAGD_GEN_COPY_STEP(
- &Points[j][CAGD_MESH_UV(Srf, i, VLen1 - 1)],
- &Points2[j][CAGD_MESH_UV(Srf2, i, 0)],
- VLen2, ULen1, ULen1, CagdRType);
- }
- else {
- /* Copy col of 2nd srf order after and lin. interp. */
- CAGD_GEN_COPY_STEP(
- &Points[j][CAGD_MESH_UV(Srf, i, VLen1 + VOrder - 2)],
- &Points2[j][CAGD_MESH_UV(Srf2, i, 0)],
- VLen2, ULen1, ULen1, CagdRType);
- InterpolateLinearSeg(
- &Points[j][CAGD_MESH_UV(Srf, i, VLen1 - 1)],
- &Points[j][CAGD_MESH_UV(Srf, i, VLen1 + VOrder - 2)],
- VOrder, ULen1);
- }
- }
- }
- break;
- default:
- Srf = NULL;
- FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
- break;
- }
-
- CagdSrfFree(Srf1);
- CagdSrfFree(Srf2);
-
- return Srf;
- }
-
- /******************************************************************************
- * Merge a list of surfaces, in order. *
- ******************************************************************************/
- CagdSrfStruct *CagdMergeSrfList(CagdSrfStruct *SrfList, CagdSrfDirType Dir,
- CagdBType SameEdge)
- {
- if (SrfList != NULL && SrfList -> Pnext != NULL) {
- CagdSrfStruct
- *MergedSrf = CagdSrfCopy(SrfList);
-
- for (SrfList = SrfList -> Pnext;
- SrfList != NULL;
- SrfList = SrfList -> Pnext) {
- CagdSrfStruct
- *TmpSrf = CagdMergeSrfSrf(MergedSrf, SrfList, Dir, SameEdge);
-
- CagdSrfFree(MergedSrf);
- MergedSrf = TmpSrf;
- }
- return MergedSrf;
- }
- else
- return SrfList ? CagdSrfCopy(SrfList) : NULL;
- }
-
- /******************************************************************************
- * Linearly interpolate between V1 and V2 values Len times (Len includes V1 *
- * and V2) and step the array using Step. *
- ******************************************************************************/
- static void InterpolateLinearSeg(CagdRType *V1, CagdRType *V2, int Len,
- int Step)
- {
- int i;
- CagdRType
- *V = V1 + Step;
-
- if (Len-- <= 2)
- return; /* No middle points to interp. */
-
- for (i = 1; i < Len; i++) {
- *V = (i * (*V2) + (Len - i) * (*V1)) / Len;
-
- V += Step;
- }
- }
-